use super::super::method::{Method, MethodType};
use super::super::value::{Value, ValueData, ValueWrapper};
use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::rc::Rc;

/// 集合类型的实现
pub struct Set;

impl Set {
    /// 创建集合值
    pub fn create(elements: Vec<Value>) -> Value {
        // 使用HashSet自动去重
        let mut unique_elements = HashSet::new();

        for elem in elements {
            unique_elements.insert(ValueWrapper(elem));
        }

        let mut methods = HashMap::new();

        // 查询方法
        methods.insert(
            "长度".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    Ok(Value::number(elements.borrow().len() as f64))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "空否".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    Ok(Value::boolean(elements.borrow().is_empty()))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "包含".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements), elem) = (&args[0].data, &args[1]) {
                    let contains = elements.borrow().contains(&ValueWrapper(elem.clone()));
                    Ok(Value::boolean(contains))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "子集".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();
                    let is_subset = borrowed1.iter().all(|elem| borrowed2.contains(elem));
                    Ok(Value::boolean(is_subset))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "超集".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();
                    let is_superset = borrowed2.iter().all(|elem| borrowed1.contains(elem));
                    Ok(Value::boolean(is_superset))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "不相交".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();
                    let is_disjoint = borrowed1.iter().all(|elem| !borrowed2.contains(elem));
                    Ok(Value::boolean(is_disjoint))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        // 修改方法
        methods.insert(
            "添加".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements), elem) = (&args[0].data, &args[1]) {
                    let mut borrowed = elements.borrow_mut();
                    let is_new = !borrowed.contains(&ValueWrapper(elem.clone()));
                    borrowed.insert(ValueWrapper(elem.clone()));
                    Ok(Value::boolean(is_new))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "移除".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements), elem) = (&args[0].data, &args[1]) {
                    let mut borrowed = elements.borrow_mut();
                    let existed = borrowed.contains(&ValueWrapper(elem.clone()));
                    borrowed.remove(&ValueWrapper(elem.clone()));
                    Ok(Value::boolean(existed))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "清空".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    elements.borrow_mut().clear();
                    Ok(args[0].clone())
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "弹出".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    let mut borrowed = elements.borrow_mut();
                    if let Some(elem) = borrowed.iter().next() {
                        let elem = elem.clone();
                        borrowed.remove(&elem);
                        Ok(elem.0)
                    } else {
                        Err("集合为空".to_string())
                    }
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        // 集合运算
        methods.insert(
            "并".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();

                    let mut new_elements = borrowed1.clone();
                    for elem in borrowed2.iter() {
                        new_elements.insert(elem.clone());
                    }

                    let result_values: Vec<Value> = new_elements.into_iter().map(|v| v.0).collect();
                    Ok(Value::set(result_values))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "交".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();

                    let mut new_elements = HashSet::new();
                    for elem in borrowed1.iter() {
                        if borrowed2.contains(elem) {
                            new_elements.insert(elem.clone());
                        }
                    }

                    let result_values: Vec<Value> = new_elements.into_iter().map(|v| v.0).collect();
                    Ok(Value::set(result_values))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "差".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();

                    let mut new_elements = HashSet::new();
                    for elem in borrowed1.iter() {
                        if !borrowed2.contains(elem) {
                            new_elements.insert(elem.clone());
                        }
                    }

                    let result_values: Vec<Value> = new_elements.into_iter().map(|v| v.0).collect();
                    Ok(Value::set(result_values))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "对称差".to_string(),
            Method::native(MethodType::Set, |args| {
                if let (ValueData::Set(elements1), ValueData::Set(elements2)) =
                    (&args[0].data, &args[1].data)
                {
                    let borrowed1 = elements1.borrow();
                    let borrowed2 = elements2.borrow();

                    let mut new_elements = HashSet::new();

                    // 添加在1中但不在2中的元素
                    for elem in borrowed1.iter() {
                        if !borrowed2.contains(elem) {
                            new_elements.insert(elem.clone());
                        }
                    }

                    // 添加在2中但不在1中的元素
                    for elem in borrowed2.iter() {
                        if !borrowed1.contains(elem) {
                            new_elements.insert(elem.clone());
                        }
                    }

                    let result_values: Vec<Value> = new_elements.into_iter().map(|v| v.0).collect();
                    Ok(Value::set(result_values))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        // 转换方法
        methods.insert(
            "复制".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    let new_elements = elements.borrow().clone();
                    let result_values: Vec<Value> = new_elements.into_iter().map(|v| v.0).collect();
                    Ok(Value::set(result_values))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "转列表".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    let new_elements: Vec<Value> =
                        elements.borrow().iter().map(|v| v.0.clone()).collect();
                    Ok(Value::list(new_elements))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        methods.insert(
            "转组".to_string(),
            Method::native(MethodType::Set, |args| {
                if let ValueData::Set(elements) = &args[0].data {
                    let new_elements: Vec<Value> =
                        elements.borrow().iter().map(|v| v.0.clone()).collect();
                    Ok(Value::tuple(new_elements))
                } else {
                    Err("不是集合类型".to_string())
                }
            }),
        );

        // 添加通用方法
        super::super::value::Value::add_common_methods(&mut methods, "汇");

        Value {
            type_name: "汇".to_string(),
            data: ValueData::Set(Rc::new(RefCell::new(unique_elements))),
            methods: Rc::new(RefCell::new(methods)),
        }
    }
}
